package cn.tedu.charging.order.websocket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint("/ws/server/{userId}")
public class WebSocketServer {
    /**
     *  本地map
     *  key 用户id  value 用户id对应的会话
     *  4大问题
     *  1 数据量
     *  2 持久化
     *  3 线程安全 ConcurrentHashMap
     *  4 分布式
     */
    private static ConcurrentHashMap<Integer, Session>
            sessionMap = new ConcurrentHashMap<>();

    /**
     * /ws/server/{userId} 从地址通过PathParam 拿到 userId
     * onOpen 方法入参 用户id 对应的session
     * 建立连接成功调用的方法, 类似 mqtt MqttConsumer#connectComplete
     * @param session
     * @param userId
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Integer userId) {
        log.debug("onOpen");
        sessionMap.put(userId,session);
        log.debug("用户:{},连接成功:{}", userId, session.getId());
    }

    /**
     * 消息到达  类似 mqtt MqttConsumer#messageArrived ,设备的消息到服务端(订单服务)
     * onMessage 用户的消息到服务端(订单服务)
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session){
        log.debug("服务器收到了用户:{},发送的消息:{}",session,message);
    }

    /**
     * 出现问题时调用此方法,具体的错误原因 throwable,谁出现的问题呢  session
     * @param session
     * @param throwable
     */
    @OnError
    public void onError(Session session, Throwable throwable){
        log.debug("onError", throwable);
    }

    /**
     * 用户关闭连接
     * @param session
     * @param userId
     */
    @OnClose
    public void onClose(Session session,@PathParam("userId") Integer userId){
        log.debug("onClose");
        //清除用户对应的会话信息
        sessionMap.remove(userId);
        log.debug("用户:{},下线", userId);
    }

    public Boolean sendMessage(Integer userId, String message){
        Session session = sessionMap.get(userId);
        if (session != null) {
            try {
                session.getBasicRemote().sendText(message);
                return true;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }else {
            log.error("用户:{},已下线",userId);
        }
        return false;
    }
}
